# -*- encoding:utf-8 -*-
# @time: 2023/3/21 22:31
# @author: Maxs_hu
from django import forms
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.forms import widgets
from django.http import JsonResponse, HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render
from django.urls import reverse

from utils import response
from utils.encrypt import md5
from utils.pager import pagination
from utils.response import baseResponse
from web import models


class customerModelForm(forms.ModelForm):
    def __init__(self, request, *args, **kwargs):
        # 此处可能用到request
        super().__init__(*args, **kwargs)

        self.fields['level'].queryset = models.Level.objects.filter(active=1)  # 定制active必须为1

        for name, field in self.fields.items():
            if name == 'level':  # cr当为level时. 不需要为radio添加样式
                continue
            field.widget.attrs['class'] = 'form-control'

    # 自定义字段验证手机号
    # mobile = forms.CharField(validators=[RegexValidator(r'^\d{11}$', '手机号格式错误'), ])

    confirm_password = forms.CharField(
        label="重复密码",
        widget=widgets.PasswordInput(
            attrs={
                'placeholder': '请确认密码'
            }
        )
    )

    class Meta:
        model = models.Customer
        fields = ['username', 'password', 'confirm_password', 'mobile', 'level']
        widgets = {
            'username': forms.TextInput(attrs={'placeholder': '请输入用户名'}),
            'password': forms.PasswordInput(attrs={'placeholder': '请输入密码'}),
            'mobile': forms.TextInput(attrs={'placeholder': '请输入手机号'}),
            'level': forms.RadioSelect(attrs={'class': 'form-radio'})
        }

    # def clean_mobile(self):
    #     mobile = self.cleaned_data['mobile']
    #     # 验证电话号码
    #     import re
    #     if not re.match('^\d{11}$', mobile):  # 十一位数字
    #         raise ValidationError('手机号格式错误')

    def clean_password(self):
        # md5加密
        password = md5((self.cleaned_data['password']))
        return password

    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = md5(self.cleaned_data['confirm_password'])
        if password != confirm_password:
            raise ValidationError('密码不一致')


def customer_list(request):
    keyword = request.GET.get('keyword', "")

    # Q查询
    q = Q()
    if keyword:
        keyword = keyword.strip()
        q.connector = 'OR'
        q.children.append(('username__contains', keyword))
        q.children.append(('mobile__contains', keyword))
        q.children.append(('level__title__contains', keyword))  # __跨表查询
        q.children.append(('creator__username__contains', keyword))

    # 在html界面会存在跨表查询. 为了提升效率减少hit database次数加上select_related
    queryset = models.Customer.objects.filter(q).filter(active=1).select_related('level', 'creator')  # 加上foreign_key字段
    # print(queryset.query)  # 当前查询的sql

    # 封装的分页对象
    obj = pagination(request, queryset)
    context = {
        'show_data': obj.show_data,
        'pager_string': obj.html(),
        'keyword': keyword
    }
    return render(request, 'customer_list.html', context)


def customer_add(request):
    if request.method == 'GET':
        form = customerModelForm(request)
        return render(request, 'customer_add.html', {'form': form})
    form = customerModelForm(request, data=request.POST)
    if not form.is_valid():
        return render(request, 'customer_add.html', {'form': form})

    form.instance.creator_id = request.user_obj.id  # 将UserInfo中封装的数据拿过来
    form.save()  # 保存数据
    return redirect(reverse('customer_list'))


class editModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['level'].queryset = models.Level.objects.filter(active=1)  # 记得加上queryset

        for name, field in self.fields.items():
            # 添加form-control属性
            field.widget.attrs['class'] = 'form-control'  # 这里个格式要正确

    class Meta:
        model = models.Customer
        fields = ['username', 'mobile', 'level']
        widgets = {
            "username": forms.TextInput(attrs={'placeholder': '请输入用户名'}),
            "mobile": forms.TextInput(attrs={'placeholder': '请输入手机号'}),
        }


def customer_edit(request, pk):
    # 将数据查出
    obj = models.Customer.objects.filter(active=1, id=pk).first()
    if request.method == 'GET':
        form = editModelForm(instance=obj)
        return render(request, 'customer_edit.html', {'form': form})

    form = editModelForm(data=request.POST, instance=obj)
    if not form.is_valid():
        return render(request, 'customer_edit.html', {'form': form})

    form.save()
    # 处理携带参数的问题
    # 1.
    filter_string = request.GET.get('_filter')  # 拿到携带的参数
    full_url = reverse('customer_list') + "?" + filter_string  # 将参数拼接

    # 2.
    # path_url = request.GET.urlencode()
    # full_url = reverse('customer_list') + '?' + path_url
    return redirect(full_url)


class resetModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'

    confirm_password = forms.CharField(
        label='确认密码',
        widget=widgets.TextInput(attrs={'placeholder': '请再次输入密码'})
    )

    class Meta:
        model = models.Customer
        fields = ['password', 'confirm_password']
        widgets = {
            'password': widgets.TextInput(attrs={'placeholder': '请输入密码'})
        }

    def clean_password(self):
        # 对密码进行加密
        password = md5(self.cleaned_data['password'])
        return password

    def clean_confirm_password(self):
        confirm_password = self.cleaned_data['confirm_password']
        # 校验密码
        if md5(confirm_password) != self.cleaned_data['password']:
            raise ValidationError('密码不一致')
        return confirm_password


def customer_reset(request, pk):
    if request.method == 'GET':
        form = resetModelForm()
        return render(request, 'customer_reset.html', {'form': form})

    obj = models.Customer.objects.filter(active=1, id=pk).first()
    form = resetModelForm(data=request.POST, instance=obj)
    if not form.is_valid():
        return render(request, 'customer_reset.html', {'form': form})

    form.save()
    return redirect(reverse('customer_list'))


def customer_delete(request):
    res = response.baseResponse()
    if request.method == 'GET':
        try:
            nid = request.GET.get('id')
            # 删除属性
            models.Customer.objects.filter(active=1, id=nid).delete()
        except Exception as e:
            res.status = False
            res.detail = '出错了. 请联系管理员'
        return JsonResponse(res.dict, json_dumps_params={'ensure_ascii': False})


class orderModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
        self.fields['charge_type'].choices = ((1, '充值'), (2, '扣款'))  # 这样设置每次实例化都会更新一次. 比静态变量好

    # 静态变量 -> 类运行只加载一次静态变量
    # charge_type = forms.TypedChoiceField(
    #     label='类型',
    #     choices=[(1, '充值'), (2, '扣款')],
    #     coerce = int
    # )

    class Meta:
        model = models.TransactionRecord
        fields = ['charge_type', 'amount']
        error_messages = {
            'charge_type': {
                'required': '不能为空',
                'invalid': '格式错误'
            },
            'amount': {
                'required': '不能为空',
                'invalid': '格式错误'
            }
        }


def customer_list_order(request, pk):
    """ 交易管理 """
    if request.method == 'GET':
        # print(locals())
        # 获取当前用户的所有交易信息
        queryset = models.TransactionRecord.objects.filter(customer_id=pk, active=1, customer__active=1).select_related(
            'customer').order_by('-create_datetime')  # 加上-号, 按照时间顺序反向排序
        # print(queryset)
        form = orderModelForm()
        if not queryset:
            errors = '暂无数据'
            context = {
                'form': form,
                'errors': errors,
                "pk": pk
            }
            return render(request, 'customer_list_order.html', context)
        obj = pagination(request, queryset)
        context = {
            'show_data': obj.show_data,
            'pager_string': obj.html(),
            'form': form,
            "pk": pk
        }
        return render(request, 'customer_list_order.html', context)
    # 1.接收post请求校验form表单
    form = orderModelForm(data=request.POST)
    resp = baseResponse()
    if not form.is_valid():
        resp.status = False
        resp.detail = form.errors
        # print(form.errors)
        return JsonResponse(resp.dict, json_dumps_params={"ensure_ascii": False})

    # 将 更新客户账户余额 和 创建交易记录 绑定为一个事务
    from django.db import transaction
    with transaction.atomic():
        # 2.更新客户账户余额
        obj = models.Customer.objects.filter(id=pk, active=1).select_for_update().first()  # 添加排它锁
        # 余额不能为负数
        if form.cleaned_data['charge_type'] == 2:
            if obj.balance < form.cleaned_data['amount']:
                resp.status = False
                resp.detail = {'amount': ['账号余额不足']}
                return JsonResponse(resp.dict, json_dumps_params={"ensure_ascii": False})

        if form.cleaned_data['charge_type'] == 1:
            obj.balance += form.cleaned_data['amount']
        else:
            obj.balance -= form.cleaned_data['amount']
        obj.save()

        # 3.创建交易
        form.instance.customer_id = pk
        form.instance.creator_id = request.user_obj.id
        form.save()  # 将数据保存到数据库
    return JsonResponse(resp.dict, json_dumps_params={"ensure_ascii": False})



